// Copyright (C) Jari Hautio <jari.hautio@iki.fi> 2008. Licensed under GPLv2. See LICENSE.txt in solution folder.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace RyijyApp
{
    public partial class PrintForm : Form
    {
        private bool showColors;

        public bool ShowColors
        {
            get { return showColors; }
            set { showColors = value; }
        }
        private Color transparentColor = Color.Empty;
        private bool showGrid;

        public bool ShowGrid
        {
            get { return showGrid; }
            set { showGrid = value; }
        }
        private bool showCenter;
        public bool ShowCenter { get { return showCenter; } set { showCenter = value; } }
        private Bitmap image;

        public Bitmap Image
        {
            get { return image; }
            set { image = value; }
        }

        private List<Color> colors;

        public List<Color> Colors
        {
            get { return colors; }
            set 
            {
                colors = value; 
            }
        }

        private CustomPalette colorPalette;

        internal CustomPalette ColorPalette
        {
            get { return colorPalette; }
            set { colorPalette = value; }
        }

        /// <summary>
        /// Use drawing canvas for rendering image with grid
        /// </summary>
        DrawingCanvas drawingCanvas1 = new DrawingCanvas();

        enum ColorMapMode { None, Right, Bottom, OwnPage };
        ColorMapMode mapMode = ColorMapMode.None;

        /// <summary>
        /// Printing offset X
        /// </summary>
        private int currentX = 0;
        /// <summary>
        /// Printing offset Y
        /// </summary>
        private int currentY = 0;
        private bool colormapPrinted = false;
        /// <summary>
        /// how many pixels per inch are printed
        /// </summary>
        private int currentTpi = 10;

        /// <summary>
        /// List of margin options shown in combobox.
        /// </summary>
        private int[] margins = { 0, 16, 25, 50, 100}; // Inches

        /// <summary>
        /// Number of rows and columns printed.
        /// </summary>
        Size printedPages = new Size(1,1);

        private ColorLib.ColorHistogram histogram=null;
        public ColorLib.ColorHistogram Histogram { get { return histogram; } set { histogram = value; } }

        public PrintForm(Bitmap img, List<Color> colorList, CustomPalette palette)
        {
            InitializeComponent();
            foreach (int m in margins)
                comboBoxMargins.Items.Add((m/100.0).ToString("F2"));
            comboBoxMargins.SelectedIndex = 3;
            drawingCanvas1.Picture = img;
            drawingCanvas1.GridLimit = 2;
            drawingCanvas1.FitToWindow = true;
            image = img;
            checkBoxGrid.Checked = true;
            comboBoxGridStyle.SelectedIndex = 1;
            comboBoxMode.SelectedIndex = 0;
            comboBoxScale.SelectedIndex = comboBoxScale.FindString("100%");
            comboBoxStitchCount.SelectedIndex = comboBoxStitchCount.FindStringExact("10");
            comboBoxOrientation.SelectedIndex = 0;
            if (palette != null)
            {
                checkBoxColorKey.Checked = true;
                comboBoxMode.SelectedIndex = 2;
                checkBoxCenter.Checked = true;
            }
            colorPalette = palette;
            colors = colorList;
            UpdateImage();
        }

		Size FitSize( int width,  int height, Size colorSize)
        {

            if (image == null || image.Width == 0) return new Size(0, 0);
            // keep target image aspect ratio
            switch (mapMode)
            {
				case ColorMapMode.None: colorSize = new Size(0, 0); break;
				case ColorMapMode.Bottom: colorSize.Width = 0; break;
                case ColorMapMode.Right: colorSize.Height = 0; break;
				case ColorMapMode.OwnPage: colorSize = new Size(0, 0); break;

            }
            float ratio1 = Convert.ToSingle(image.Height) / image.Width ;
            float ratio2 = Convert.ToSingle(height - colorSize.Height) / (width - colorSize.Width);
            int w, h;
            if (ratio1 > ratio2)
            {
                h = height - colorSize.Height;
                w = Convert.ToInt32(h / ratio1);
            }
            else
            {
                w = width - colorSize.Width;
                h = Convert.ToInt32(ratio1 * w);
            }
            w += colorSize.Width;
            h += colorSize.Height;
            /*
            // make sure that grid lines wont dominate in picture
            if (checkBoxGrid.Checked && (pictureBox1.Width / image.Width < 3))
            {
                double f =  image.Width * 3.0 / pictureBox1.Width;
                w = Convert.ToInt32(w * f);
                h = Convert.ToInt32(h * f);
            }
            */
            return new Size(w, h);
        }
        /// <summary>
        /// Renders image and color bar to graphics.
        /// Colorbar orientation is got from mapMode variable.
        /// </summary>
        /// <param name="grPhoto"></param>
        /// <param name="w">Canvas width</param>
        /// <param name="h">Canvs height</param>
        /// <param name="cb">Colorbar size</param>
        void Render(Graphics grPhoto, int x, int y, int w, int h, float z, Size cb)
        {
            DrawImage(grPhoto, x, y, w, h, z);
            switch (mapMode)
            {
                case ColorMapMode.None:
                    break;
				case ColorMapMode.OwnPage:
					break;
				case ColorMapMode.Right:
                    DrawColors(grPhoto, w, 0, cb.Width, cb.Height, false);
                    break;
                case ColorMapMode.Bottom:
                    DrawColors(grPhoto, 0, h, cb.Width, cb.Height,false);
                    break;
            }
            if (showCenter)
            {
                // check for center
                int cx = image.Width / 2 - x;
                int cy = image.Height / 2 - y;
                float tw = Math.Min(w, (image.Width - x)*z);
                float th = Math.Min(h, (image.Height - y)*z);
                if (cx > 0 && cx < w)
                    grPhoto.DrawLine(Pens.DarkRed, new PointF(cx*z, 0), new PointF(cx*z, th));
                if (cy > 0 && cy < h)
                    grPhoto.DrawLine(Pens.DarkRed, new PointF(0,cy*z), new PointF(tw,cy*z));
                if (cx > 0 && cx < w && cy > 0 && cy < h)
                {
                    int zz = Convert.ToInt32(z) / 2;
                    cx = Convert.ToInt32(cx*z);
                    cy = Convert.ToInt32(cy*z);
                    using (Pen p1 = new Pen(Color.DarkRed, 3))
                    {
                        grPhoto.DrawLine(p1, new Point(cx - zz, cy - zz), new Point(cx + zz, cy + zz));
                        grPhoto.DrawLine(p1, new Point(cx - zz, cy + zz), new Point(cx + zz, cy - zz));
                        grPhoto.DrawLine(Pens.Red, new Point(cx - zz, cy - zz), new Point(cx + zz, cy + zz));
                        grPhoto.DrawLine(Pens.Red, new Point(cx - zz, cy + zz), new Point(cx + zz, cy - zz));
                    }
                }
            }

        }
        void UpdateImage()
        {
			/*
            if (image == null || image.Width == 0) return;
            Size cb = new Size(0,0);
            if (mapMode != ColorMapMode.None && mapMode != ColorMapMode.OwnPage)
            {
                using (Graphics g = Graphics.FromHwnd(Handle))
                {
                    cb = CalculateColorBox(g, pictureBox1.Width, pictureBox1.Height);
                }
            }
            int w = pictureBox1.Width;
            int h = pictureBox1.Height;
            Size sz = FitSize(w, h,  cb);
            w = sz.Width > cb.Width ? sz.Width : cb.Width;
            h = sz.Height > cb.Height ? sz.Height : cb.Height;
                        
            Bitmap bmPhoto = new Bitmap(w, h, PixelFormat.Format24bppRgb);
            using (Graphics g = Graphics.FromHwnd(Handle))
            {
                bmPhoto.SetResolution(g.DpiX, g.DpiY);
            }

            drawingCanvas1.EmptySymbolColor = transparentColor;
            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            using (Brush br = new SolidBrush(BackColor))
                grPhoto.FillRectangle(br, 0, 0, w, h);
            Render(grPhoto, sz.Width, sz.Height, cb);
            grPhoto.Dispose();

            pictureBox1.Image = bmPhoto;
			 */
			printPreviewControl1.Document = printDocument1;
			printPreviewControl1.InvalidatePreview();

        }
        Color MultiplyColor(Color c, ColorMatrix m)
        {
            return Color.FromArgb(
                Convert.ToInt32(c.R * m[0, 0] + c.G * m[1, 0] + c.B * m[2, 0] + 255*m[4, 0]),
                Convert.ToInt32(c.R * m[0, 1] + c.G * m[1, 1] + c.B * m[2, 1] + 255*m[4, 1]),
                Convert.ToInt32(c.R * m[0, 2] + c.G * m[1, 2] + c.B * m[2, 2] + 255*m[4, 2])
                );
        }
        private Size CalculateColorBox(Graphics g, int w, int h)
        {
            Size s = new Size(w,h);
            if (colors == null || colors.Count == 0) 
                return new Size(0, 0);

            SizeF fs = new SizeF(64,14);
            if (g != null)
            {
                using (Font f = new Font("Arial", 8))
                    fs = g.MeasureString("XXXXXXXX", f);
            }

            if (mapMode == ColorMapMode.Bottom)
            {
                // horizontal layout
                int cols = Convert.ToInt32(w / fs.Width);
                s.Height = Convert.ToInt32(Math.Ceiling((double)colors.Count / cols) * fs.Height);
                if (s.Height > h / 2) s.Height = h / 2; // hard limit to half page
            }
            else if (mapMode == ColorMapMode.Right)
            {
                // vertical layout
                int rows = Convert.ToInt32(h / fs.Height);
                s.Width = Convert.ToInt32(Math.Ceiling((double)colors.Count / rows) * fs.Width);
                if (s.Width> w / 2) s.Width = w / 2; // hard limit to half page
            }
            else // none
            {
                s.Width = 0;
                s.Height = 0;
            }
            if (s.Width > w) s.Width = w;
            if (s.Height > h) s.Height = h;
            return s;
        }

        private void DrawColors(Graphics grPhoto, int x, int y, int w, int h, bool tableLayout)
        {
            if (colors == null || colors.Count == 0|| w==0 || h==0) return;

            // Find a font that can fit the data
            int fontsize = 8;
            string teststring = "XXXXXXXX";
            Font f = new Font("Arial", fontsize);
            SizeF fs = grPhoto.MeasureString(teststring, f);
            int maxrows = Convert.ToInt32(h / fs.Height);
            int cols = tableLayout ? colors.Count / maxrows + 1 : Convert.ToInt32(w / fs.Width);
            int rows = Convert.ToInt32(Math.Ceiling((double)colors.Count / cols));
            int maxTableCols= 4;
            while (fontsize >= 4)
            {
                if (f!= null) f.Dispose();
                f = new Font("Arial", fontsize);
                fs = grPhoto.MeasureString(teststring, f);
			    maxrows = Convert.ToInt32(h / fs.Height);
                if (tableLayout)
                {
                    cols = 1+colors.Count / maxrows;
                    // Max four columns per page
                    if (cols > maxTableCols) cols = maxTableCols;
                    maxTableCols++;
                } else cols = Convert.ToInt32(w / fs.Width);
                rows = Convert.ToInt32(Math.Ceiling((double)colors.Count / cols));
                // if table, reserve space for header row
                if (tableLayout) rows++;
                // test if fits 
                if (rows * fs.Height <= h)
                    break;
                if (teststring.Length > 6)
                    teststring = teststring.Substring(1);
                else
                {
                    fontsize--;
                    if (teststring.Length > 3) teststring = teststring.Substring(1);
                }
            }
            if (cols < 1) cols = 1;
            w /= cols;
            if (tableLayout &&  cols == 1) w /= 2;
            float d = fs.Height;
            int colorWidth = tableLayout ? Convert.ToInt32(d*(1 + 4 / cols)) : w;

            // don't draw if wont fit
            if (d < 1)
            {
                f.Dispose();
                return;
            }

            bool symbols = drawingCanvas1.SymbolDrawingMode != DrawingCanvas.SymbolMode.None;
            if (tableLayout)
            {
                float textpos = x + (symbols ? d : 0);
                if (colorPalette != null)
                    grPhoto.DrawString(colorPalette.PaletteName, f, Brushes.Black, textpos+0.1f*w, y);
                grPhoto.DrawString("#", f, Brushes.Black, 
                    new RectangleF( textpos + 0.8f * w, y, x+w, y+d));

                y += Convert.ToInt32(d);

            }
            ColorMatrix m = drawingCanvas1.ImageColorMatrix;
            for (int i = 0; i < colors.Count; i++)
            {
				float textpos = symbols ? d : 0;
				Color bg = colors[i];
                if (m != null)
                {
                    bg = MultiplyColor(bg, m);
                }
                Point pos = new Point(x + (i % cols) * w, y + Convert.ToInt32((i / cols) * d));
                if (tableLayout) textpos = colorWidth;

				using (Brush b = new SolidBrush(bg))
				{
                    if (!tableLayout) grPhoto.FillRectangle(b, pos.X, pos.Y, colorWidth, d);
                    else grPhoto.FillRectangle(b, pos.X, pos.Y, colorWidth, d);
				}

                    if (drawingCanvas1.SymbolDrawingMode != DrawingCanvas.SymbolMode.None &&
                        colors[i] != transparentColor)
                    {
                        drawingCanvas1.Symbols.DrawSymbol(grPhoto, new RectangleF(pos.X, pos.Y, d, d), colors[i]);
                    }
                    if (d >= 4)
                    {
                        grPhoto.DrawRectangle(tableLayout? Pens.Black : Pens.White, pos.X,pos.Y, w, d);
                        if (colorPalette != null)
                        {
                            string text;
                            if (tableLayout)
                            {

                                text = " " + colorPalette.GetTextAndName(colors[i]);
                                grPhoto.DrawString(text, f, Brushes.Black,
                                    RectangleF.FromLTRB(pos.X + textpos, pos.Y, pos.X + w * 0.8f, pos.Y + d));

                                int num = 0;
                                if (histogram != null && histogram.TryGetValue(colors[i], ref num))
                                {
                                    grPhoto.DrawString(num.ToString(), f, Brushes.Black,
                                        RectangleF.FromLTRB(pos.X + w * 0.8f, pos.Y, pos.X + w, pos.Y + d));
                                }
                            }
                            else
                            {
                                text = colorPalette.GetName(colors[i]);
                                grPhoto.DrawString(text,
                                    f,
                                    (symbols || tableLayout) ? Brushes.Black : colors[i].GetBrightness() < 0.4 ? Brushes.White : Brushes.Black,
                                    RectangleF.FromLTRB(pos.X + textpos, pos.Y, pos.X + w, pos.Y + d));
                            }
                        }
                        else if (tableLayout) // no color palette add RGB values to table
                        {
                            string text = String.Format("RGB:({0},{1},{2})",
                                colors[i].R, colors[i].G, colors[i].B);
                            grPhoto.DrawString(text, f, Brushes.Black,
                                RectangleF.FromLTRB(pos.X + textpos, pos.Y, pos.X + w * 0.8f, pos.Y + d));
                            textpos += w * 0.8f;
                            int num = 0;
                            if (histogram != null && histogram.TryGetValue(colors[i], ref num))
                            {
                                grPhoto.DrawString(num.ToString(), f, Brushes.Black,
                                    RectangleF.FromLTRB(pos.X + textpos, pos.Y, pos.X + w, pos.Y + d));
                            }
                        }
                    }
            }
            if (f != null)
                f.Dispose();
        }

        private void DrawImage(Graphics grPhoto, int x, int y,int width, int height, float zoom)
        {
            drawingCanvas1.EmptySymbolColor = transparentColor;
            if (checkBoxGrid.Checked)
            {
                DrawingCanvas.GridStyles gs = (DrawingCanvas.GridStyles)comboBoxGridStyle.SelectedIndex + 1;
                
                if (comboBoxGridStyle.SelectedIndex != 3)
                {
                    if (drawingCanvas1.GridStyle != gs ||
                        drawingCanvas1.GridLimit != 5)
                    {
                        drawingCanvas1.GridLimit = 5;
                        drawingCanvas1.GridStyle = gs;
                    }
                }
                else
                {
                    drawingCanvas1.GridLimit = 1000;
                    drawingCanvas1.GridStyle = DrawingCanvas.GridStyles.Black;
                }
            }
            else
            {
                drawingCanvas1.GridStyle = DrawingCanvas.GridStyles.None;
            }
            drawingCanvas1.Render(grPhoto, x,y, width, height, zoom);
        }
        private void button2_Click(object sender, EventArgs e)
        {
            showColors = mapMode != ColorMapMode.None && mapMode != ColorMapMode.OwnPage;
            showGrid = checkBoxGrid.Checked;
//            image = pictureBox1.Image;
            printDialog1.Document = printDocument1;
            if (printDialog1.ShowDialog() == DialogResult.OK)
            {
                printDocument1.Print();
                Close();
            }
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void checkBoxColors_CheckedChanged(object sender, EventArgs e)
        {
            UpdateImage();
        }

        private void checkBoxGrid_CheckedChanged(object sender, EventArgs e)
        {
            comboBoxGridStyle.Enabled = checkBoxGrid.Checked;
            UpdateImage();
        }

        private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            int x = Convert.ToInt32(e.PageSettings.Bounds.Left + e.PageSettings.Margins.Left);
            int y = Convert.ToInt32(e.PageSettings.Bounds.Top + e.PageSettings.Margins.Top);
            SizeF areaSize = GetDrawableArea(e.PageSettings);
            int w = areaSize.ToSize().Width;
            int h = areaSize.ToSize().Height;

            Size cb = CalculateColorBox(e.Graphics, w, h);
            e.HasMorePages = false;

            // reserve space for annotations 
            if (checkBoxGrid.Checked)
            {
                using (Font f = new Font("Arial", 8))
                {
                    SizeF sz = e.Graphics.MeasureString("X", f);
                    w -= Convert.ToInt32(Math.Floor(sz.Width));
                    h -= Convert.ToInt32(Math.Floor(sz.Height));
                    x += Convert.ToInt32(Math.Floor(sz.Width));
                    y += Convert.ToInt32(Math.Floor(sz.Height));
                }
            }

            if (mapMode == ColorMapMode.Bottom)
                h -= cb.Height;
            if (mapMode == ColorMapMode.Right)
                w -= cb.Width;



            Size size = FitSize(w, h, cb);
            // now calculate how many squares fit to page
            float z = 100 / ( currentTpi>0 ? currentTpi : 10);
            w = Convert.ToInt32(Convert.ToInt32(w / z) * z);
            h = Convert.ToInt32(Convert.ToInt32(h / z) * z);
            if (currentX < image.Width &&
                currentY < image.Height)
            {
                e.Graphics.TranslateTransform(x, y);
                Render(e.Graphics, currentX, currentY, w, h, z, cb);
                e.Graphics.ResetTransform();

                int rows = h / (100 / currentTpi);
                int cols = w / (100 / currentTpi);
                if (rows > (image.Height-currentY)) rows = image.Height - currentY;
                if (cols > (image.Width-currentX)) cols = image.Width - currentX;
                // Add annotations every ten stitches
                if (checkBoxGrid.Checked)
                {
                    using (Font f = new Font("Arial", 8))
                    {
                        SizeF sz = e.Graphics.MeasureString("X", f);
                        int ax = currentX % 10 == 0 ? currentX : (currentX - currentX % 10 + 10);
                        int ay = currentY % 10 == 0 ? currentY : (currentY - currentY % 10 + 10);
                        for (; ax <= currentX+cols; ax += 10)
                            e.Graphics.DrawString(ax.ToString(), f, Brushes.Black,
                                new PointF(x + (ax - currentX) * z, y - sz.Height));
                        for (; ay <= currentY+rows; ay += 10)
                            e.Graphics.DrawString(ay.ToString(), f, Brushes.Black, 
                                new RectangleF(x - sz.Width, y + (ay - currentY) * z, sz.Width, 4*sz.Height));

                    }
                }

                if (currentY == 0)
                    printedPages.Width++;
                currentX += cols;
                if (currentX >= image.Width)
                {
                    currentX = 0;
                    currentY += rows;
                    printedPages.Height++;
                }
            }
            else if (checkBoxColorKey.Checked && !colormapPrinted)
            {
                e.Graphics.TranslateTransform(x, y);
                DrawColors(e.Graphics, 0, 0, w, h, true);
                e.Graphics.ResetTransform();
                colormapPrinted = true;
                printedPages.Height++;

            }
            else return; // no more pages

            e.HasMorePages = currentY < image.Height || ( checkBoxColorKey.Checked && !colormapPrinted);

        }

        private void PrintForm_Load(object sender, EventArgs e)
        {

        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                int z = 10;
                int w = image.Width * z;
                int h = image.Height * z;

                Size cb = new Size(0, 0);
                if (mapMode!= ColorMapMode.None)
                {
                    Graphics gg =  Graphics.FromImage(image);
                    cb = CalculateColorBox(gg, w, h);
                    gg.Dispose();
                }

                Bitmap bm = new Bitmap( w + (mapMode == ColorMapMode.Right ? cb.Width : 0),
                                        h + (mapMode == ColorMapMode.Bottom ? cb.Height : 0));


                Size sz = FitSize(w, h, cb);
                Graphics g = Graphics.FromImage(bm);
                g.FillRectangle(Brushes.White, 0, 0, w, h);
                Render(g, 0,0, sz.Width, sz.Height, z, cb);
                g.Dispose();

                bm.Save(saveFileDialog1.FileName);
            }
        }

        private void panel1_Resize(object sender, EventArgs e)
        {
//            UpdateImage();
        }

        private void comboBoxGridStyle_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateImage();
        }

        private void comboBoxMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            drawingCanvas1.SymbolDrawingMode = (DrawingCanvas.SymbolMode)comboBoxMode.SelectedIndex;
            checkBoxTransparentBg.Enabled =
                (drawingCanvas1.SymbolDrawingMode != DrawingCanvas.SymbolMode.None);

            UpdateImage();
        }


        private void checkBoxTransparentBg_CheckedChanged(object sender, EventArgs e)
        {
            if (image == null) return;

            if (!checkBoxTransparentBg.Checked)
            {
                transparentColor = Color.Empty;
                UpdateImage();
                return;
            }
            if (image.Width < 2 || image.Height < 2)
            {
                transparentColor = Color.Empty;
                return;
            }
            // select transparent color
            SortedDictionary<int, int> d = new SortedDictionary<int,int>();
            for (int x = 0; x < image.Width; x++)
            {
                int c = image.GetPixel(x, 0).ToArgb(); ;
                if (d.ContainsKey(c)) d[c]++;
                else d.Add(c, 1);
                c = image.GetPixel(x, image.Height-1).ToArgb();
                if (d.ContainsKey(c)) d[c]++;
                else d.Add(c, 1);
            }

            for (int y = 0; y < image.Height; y++)
            {
                int c = image.GetPixel(0, y).ToArgb();
                if (d.ContainsKey(c)) d[c]++;
                else d.Add(c, 1);
                c = image.GetPixel(image.Width-1, y).ToArgb();
                if (d.ContainsKey(c)) d[c]++;
                else d.Add(c, 1);
            }
            // pick color with most pixels
            int n=0;
            Color col = Color.Empty;
            foreach (KeyValuePair<int, int> item in d)
            {
                if (item.Value > n)
                {
                    col = Color.FromArgb(item.Key);
                    n = item.Value;
                }
            }
            transparentColor = col;
            UpdateImage();
        }

		private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
		{
            currentX = 0;
            currentY = 0;
            printedPages.Height = 0;
            printedPages.Width = 0;
            colormapPrinted = false;
		}

		private void buttonPreview_Click(object sender, EventArgs e)
		{
			printPreviewDialog1.Document = printDocument1;
			printPreviewDialog1.ShowDialog();
		}

        private void comboBoxScale_SelectedIndexChanged(object sender, EventArgs e)
        {
            int zoom = Convert.ToInt32(comboBoxScale.Text.TrimEnd('%'));
            printPreviewControl1.Zoom = zoom / 100.0;
        }

        private void comboBoxColors_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = comboBoxColors.SelectedIndex;
            switch (index)
            {
                case 0:
                    mapMode = ColorMapMode.None;
                    break;
                case 1:
                    mapMode = ColorMapMode.Right;
                    break;
                case 2:
                    mapMode = ColorMapMode.Bottom;
                    break;
                case 3:
                    mapMode = ColorMapMode.OwnPage;
                    break;
                default:
                    mapMode = ColorMapMode.None;
                    break;
            }
            UpdateImage();
        }
        private SizeF GetDrawableArea(System.Drawing.Printing.PageSettings settings)
        {
            SizeF sz = settings.Bounds.Size;

            sz.Width -= settings.Margins.Left +
                settings.Margins.Right;
            sz.Height -= settings.Margins.Top +
                settings.Margins.Bottom;
            return sz;
        }

        private void comboBoxStitchCount_SelectedIndexChanged(object sender, EventArgs e)
        {
            int n =0;
            try
            {
                n = Convert.ToInt32(comboBoxStitchCount.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            currentTpi = n;
            UpdateImage();
        }

        private void comboBoxOrientation_SelectedIndexChanged(object sender, EventArgs e)
        {
            printDocument1.DefaultPageSettings.Landscape = comboBoxOrientation.SelectedIndex == 1;
            UpdateImage();
        }

        private void checkBoxCenter_CheckedChanged(object sender, EventArgs e)
        {
            showCenter = checkBoxCenter.Checked;
            UpdateImage();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                int m = margins[comboBoxMargins.SelectedIndex];
                printDocument1.DefaultPageSettings.Margins.Bottom = m;
                printDocument1.DefaultPageSettings.Margins.Left = m;
                printDocument1.DefaultPageSettings.Margins.Top = m;
                printDocument1.DefaultPageSettings.Margins.Right = m;
                UpdateImage();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
        {
            // Set pages
            printPreviewControl1.Columns = printedPages.Width;
            printPreviewControl1.Rows = printedPages.Height;
        }

        private void checkBoxColorKey_CheckedChanged(object sender, EventArgs e)
        {
            UpdateImage();
        }

    }
}